﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using LeoK.Annotations;
using LeoK.Common;
using LeoK.TM.Entity;
using MySql.Data.MySqlClient;
using Telerik.Windows.Controls.ChartView;
using Telerik.Windows.Controls.Gauge;

namespace LeoK.TM
{
    /// <summary>
    /// ReportA.xaml 的交互逻辑
    /// </summary>
    public partial class ReportA : UserControl
    {
        private List<DayPointSeries> _dayPointSeries = new List<DayPointSeries>();

        public ReportA()
        {
            InitializeComponent();

            DataSpanSelector.SelectionChanged = DataSpanSelectionChanged;
            Loaded += (sender, args) => { DataSpanSelectionChanged(); };
        }

        private async void DataSpanSelectionChanged()
        {
            _dayPointSeries = new List<DayPointSeries>();
            string sql = @"SELECT R.Date,R.Name,CAST(SUM(R.TimeSpan) AS SIGNED) AS Amount,R.ColorFlag FROM 
                        (
	                        SELECT S.ColorFlag, DATE(TL.StartTime) AS Date,S.Name,TL.TimeSpan FROM TM_TimeLine TL
	                        INNER JOIN TM_Task T ON TL.TID = T.ID
	                        INNER JOIN TM_Sln S ON T.SlnID=S.ID
                            WHERE DATE(TL.StartTime) >= @StartDate AND DATE (TL.StartTime) <= @EndDate
                        ) AS R
                        GROUP BY R.Date,R.Name,R.ColorFlag ORDER BY R.Date";
            List<MySqlParameter> paras = new List<MySqlParameter>();
            paras.Add(new MySqlParameter("StartDate", DataSpanSelector.StartDate));
            paras.Add(new MySqlParameter("EndDate", DataSpanSelector.EndDate));
            

            using (MySqlDB db = new MySqlDB())
            {
                DataTable table = await db.ExecuteDataTable(sql, paras);
                DataTable nameTable = table.DefaultView.ToTable(true, "Name", "ColorFlag");

                foreach (DataRow row in nameTable.Rows)
                {
                    CreateDaySeries(row, table);
                }

                CreateSumDaySeries();
                CreateLinerSeries();
                CreateSlnPieData();

                lstLegend.ItemsSource = _dayPointSeries;
            }

            CreateTimeBar();
        }

        private void CreateLinerSeries()
        {
            chart.Series.Clear();
            foreach (DayPointSeries dayPointSeries in _dayPointSeries)
            {
                LineSeries lineSeries = new LineSeries();
                lineSeries.Visibility = Visibility.Collapsed;
                chart.Series.Add(lineSeries);
                lineSeries.DataContext = dayPointSeries;
                lineSeries.Stroke = dayPointSeries.LineColor;
                lineSeries.PointTemplate = (DataTemplate)Resources["pointTemplate"];
                lineSeries.CategoryBinding = new PropertyNameDataPointBinding("Date");
                lineSeries.ValueBinding = new PropertyNameDataPointBinding("Value");
                lineSeries.SetBinding(ChartSeries.ItemsSourceProperty, new Binding("DayPoints"));
                lineSeries.SetBinding(ChartSeries.VisibilityProperty, new Binding("IsSelected") {Converter = new BooleanToVisibilityConverter()});
                lineSeries.Loaded += (sender, args) =>
                {
                    lineSeries.SetBinding(CartesianSeries.VerticalAxisProperty, new Binding() { ElementName = "VAxis" });
                    lineSeries.SetBinding(CartesianSeries.HorizontalAxisProperty, new Binding() { ElementName = "HAxis" });
                };
            }
        }

        private void CreateDaySeries(DataRow row, DataTable table)
        {
            DayPointSeries dayPointSeries = new DayPointSeries();
            dayPointSeries.Name = row["Name"].ToString();
            string colorFlag = row["ColorFlag"].ToString();
            if (colorFlag.Length == 0)
            {
                colorFlag = "#FFFFFFFF";
            }
            dayPointSeries.LineColor = new SolidColorBrush((Color)ColorConverter.ConvertFromString(colorFlag));
            List<DataRow> rows = table.Select("Name='" + row["Name"] + "'", "Date").ToList();
            DateTime curDate = DataSpanSelector.StartDate;

            while (curDate < DataSpanSelector.EndDate)
            {
                int value = 0;
                DataRow curDayRow = rows.FirstOrDefault(p => DateTime.Parse(p["Date"].ToString()) == curDate);
                if (curDayRow != null)
                {
                    value = Int32.Parse(curDayRow["Amount"].ToString());
                }

                dayPointSeries.DayPoints.Add(new DayPoint() { Date = curDate, Value = value });
                curDate = curDate.AddDays(1);
            }

            dayPointSeries.PropertyChanged += (sender, args) =>
            {
                if (args.PropertyName == "IsSelected")
                {
                    if (dayPointSeries.IsSelected)
                    {
                        _dayPointSeries[0].IsSelected = false;
                    }
                }
            };
            _dayPointSeries.Add(dayPointSeries);
        }

        private void CreateSumDaySeries()
        {
            DayPointSeries sumDayPointSeries = new DayPointSeries();
            sumDayPointSeries.Name = "全部";
            sumDayPointSeries.IsSelected = true;
            sumDayPointSeries.LineColor = new SolidColorBrush(Colors.DarkRed);
            DateTime curDate = DataSpanSelector.StartDate;

            while (curDate < DataSpanSelector.EndDate)
            {
                int value = 0;;
                foreach (DayPointSeries dayPointSeries in _dayPointSeries)
                {
                    value += dayPointSeries.DayPoints.FirstOrDefault(p => p.Date == curDate).Value;
                }

                sumDayPointSeries.DayPoints.Add(new DayPoint() { Date = curDate, Value = value });
                curDate = curDate.AddDays(1);
            }

            _dayPointSeries.Insert(0, sumDayPointSeries);
            sumDayPointSeries.PropertyChanged += (sender, args) =>
            {
                if (args.PropertyName == "IsSelected")
                {
                    if (sumDayPointSeries.IsSelected)
                    {
                        _dayPointSeries.ForEach(p =>
                        {
                            if (p != sumDayPointSeries)
                            {
                                p.IsSelected = false;
                            }
                        });
                    }
                }
            };
        }

        private void CreateSlnPieData()
        {
            List<SlnPieData> slnPieDatas = new List<SlnPieData>();
            int total = _dayPointSeries.Sum(p => p.DayPoints.Sum(p1 => p1.Value));
            PieSeries.SliceStyles.Clear();
            for (int i = 1; i < _dayPointSeries.Count; i++)
            {
                SlnPieData slnPieData = new SlnPieData();
                slnPieData.Name = _dayPointSeries[i].Name;
                slnPieData.Value = _dayPointSeries[i].DayPoints.Sum(p => p.Value);
                slnPieData.Percent = Math.Round((total == 0 ? 0 : (double) slnPieData.Value/total), 4) * 100;
                slnPieDatas.Add(slnPieData);

                Style style = new Style(typeof(Path));
                style.Setters.Add(new Setter(Shape.FillProperty, _dayPointSeries[i].LineColor));
                PieSeries.SliceStyles.Add(style);
            }

            PieSeries.ItemsSource = slnPieDatas;
        }

        private async void CreateTimeBar()
        {
            foreach (GaugeRange range in RadialScale.Ranges)
            {
                range.Min = 0;
                range.Max = 0;
            }
            RadialScale.Ranges.Clear();
            using (MySqlDB db = new MySqlDB())
            {
                List<MySqlParameter> paras = new List<MySqlParameter>();
                paras.Add(new MySqlParameter("StartDate", DataSpanSelector.StartDate));
                paras.Add(new MySqlParameter("EndDate", DataSpanSelector.EndDate));
                List<TM_TimeLine> timeLines = await db.QueryObjs<TM_TimeLine>("SELECT * FROM TM_TimeLine WHERE DATE(StartTime)>=@StartDate AND DATE(StartTime)<=@EndDate", paras);

                foreach (TM_TimeLine timeLine in timeLines)
                {
                    GaugeRange gaugeRange = new GaugeRange();
                    gaugeRange.StartWidth = 1;
                    if (timeLine.StartTime.Day == timeLine.EndTime.Day)
                    {
                        gaugeRange.Min = timeLine.StartTime.Hour + timeLine.StartTime.Minute / 60.0;
                        gaugeRange.Max = timeLine.EndTime.Hour + timeLine.EndTime.Minute / 60.0;
                    }
                    else
                    {
                        gaugeRange.Min = timeLine.StartTime.Hour + timeLine.StartTime.Minute / 60.0 ;
                        gaugeRange.Max = timeLine.EndTime.Hour + timeLine.EndTime.Minute / 60.0 + 24;
                    }
                    gaugeRange.Background = new SolidColorBrush(Colors.OrangeRed) {Opacity = 0.05};

                    RadialScale.Ranges.Add(gaugeRange);
                }
            }
        }
    }

    public class SlnPieData
    {
        public string Name { get; set; }
        public double Percent { get; set; }
        public int Value { get; set; }
    }

    public class DayPointSeries : INotifyPropertyChanged
    {
        private bool _isSelected;

        public bool IsSelected
        {
            get { return _isSelected; }
            set
            {
                _isSelected = value; 
                OnPropertyChanged();
            }
        }

        public List<DayPoint> DayPoints { get; set; }
        public string Name { get; set; }
        public SolidColorBrush LineColor { get; set; }

        public DayPointSeries()
        {
            DayPoints = new List<DayPoint>();
        }

        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public class DayPoint
    {
        public DateTime Date { get; set; }
        public int Value { get; set; }
    }
}
